﻿using System;
using System.IO;
using System.Xml.Serialization;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Data;

namespace Xin478.CSWork.Common
{
    public class DatagramBuilder 
    {
        private object[] funparams;
        private string functionName;
        const string ENDTAG="|||";

        public string Name { get { return this.functionName; } }
        public object[] Params { get { return this.funparams; } }

        public DatagramBuilder(string functionName, params object[] objs)
        {
            this.functionName = functionName;
            if (objs!=null && objs.Length > 0)
            {
                this.funparams = new object[objs.Length + 1];
                for (int i = 0; i < objs.Length; i++)
                    this.funparams[i+1] = objs[i];
            }
        }
        private DatagramBuilder(string functionName)
        {
            this.functionName = functionName;
        }

        public byte[] ToByte()
        {
            byte[] fun = System.Text.Encoding.UTF8.GetBytes(this.functionName);
            byte[] split = System.Text.Encoding.UTF8.GetBytes(ENDTAG);

            byte[] result;
            if (this.funparams!=null && this.funparams.Length > 0)
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                MemoryStream ms = new MemoryStream();
                binaryFormatter.Serialize(ms, this.funparams);
                ms.Position = 0;
                int len = (int)ms.Length;
                result = new Byte[len + fun.Length + split.Length];
                ms.Read(result, fun.Length + split.Length, len);
                ms.Close();
                Array.Copy(fun, 0, result, 0, fun.Length);
                Array.Copy(split,0, result, fun.Length,split.Length);
            }
            else
            {
                result = new Byte[fun.Length + split.Length];
                Array.Copy(fun, 0, result, 0, fun.Length);
                Array.Copy(split,0, result, fun.Length,split.Length);
            }
            return result;
        }

        public static byte[] FileToByte(string fileMd5,byte[] trick)
        {
            byte[] fun = System.Text.Encoding.UTF8.GetBytes("@"+fileMd5);
            byte[] split = System.Text.Encoding.UTF8.GetBytes(ENDTAG);

            byte[] result = new Byte[fun.Length + split.Length+trick.Length];
            Array.Copy(fun, 0, result, 0, fun.Length);
            Array.Copy(split, 0, result, fun.Length, split.Length);
            Array.Copy(trick, 0, result, fun.Length+split.Length,trick.Length);

            return result;
        }

        public static DatagramBuilder ToBuilder(byte[] data)
        {
            if (data.Length == 0) return null;

            DatagramBuilder builder;
            byte[] split = System.Text.Encoding.UTF8.GetBytes(ENDTAG);

            int j=0,i=0;
            for (; i < data.Length; i++)
            {
                if (data[i] == split[j])
                {
                    if (++j == split.Length) { ++i; break; }
                }
                else
                {
                    if (j != 0) j = 0;
                }
            }
            string fname = System.Text.Encoding.UTF8.GetString(data, 0, i-split.Length);
            if (fname.StartsWith("@")) //@文件md5
            {
                builder = new DatagramBuilder("接受文件");

                byte[] b = new byte[data.Length - i];
                Array.Copy(data, i, b, 0, b.Length);
                builder.funparams=new object[]{null,fname.Substring(1), b};
            }
            else
            {
                builder = new DatagramBuilder(fname);
                if (i < data.Length)
                {
                    //创建内存流
                    MemoryStream memStream = new MemoryStream(data, i, data.Length - i);
                    memStream.Seek(0, SeekOrigin.Begin);
                    //产生二进制序列化格式
                    IFormatter formatter = new BinaryFormatter();
                    builder.funparams = formatter.Deserialize(memStream) as object[];
                }
                else
                {
                    builder.funparams = new object[1];
                }
            }
            return builder;
        }

    }
}
